/*
 * SensorInterrupt.cpp
 *
 * Deals with sensor interrupts
 *
 * Author: Zachary Masiello
 * Author: Peter-John Rowe
 */

#include "SensorInterrupt.h"

//These aren't defined in the h file due to the fact that the thread/Interrupt needs access to them
//and the thread is static
static uintptr_t intr_handle;
volatile int _pulseCount;
volatile int _allPulseCount;
vector<timeval> values;
bool distCalc = false;
int interruptID;
struct timeval start;


SensorInterrupt::SensorInterrupt()
{
	gettimeofday(&start,0);
	for (int i=0; i<5; i++)
	{
		values.push_back(start);
	}
}

const struct sigevent *
interruptReceived(void *arg, int id)
{
	if(distCalc)
	{
		_pulseCount++;
	}
	_allPulseCount++;
	//get time since start

	//add time to beginning of values, remove any values beyond 5
	struct timeval curTime;
	gettimeofday(&curTime, 0);
	values.push_back(curTime);
	values.erase(values.begin());

	out8(intr_handle, 0x02);
	return NULL;
}

int SensorInterrupt::getCount()
{
	return _pulseCount;
}

int SensorInterrupt::getAllCount()
{
	return _allPulseCount;
}

double SensorInterrupt::getTime()
{
	struct timeval five = values.at(4);
	struct timeval four = values.at(3);
	long value = (five.tv_sec - four.tv_sec) * 1000000 + five.tv_usec - four.tv_usec;
	return (double)value / 1000000;
}

void SensorInterrupt::calcDistance(bool newValue)
{
	distCalc = newValue;
}

void SensorInterrupt::resetDistance()
{
	_pulseCount = 0;
	_allPulseCount = 0;
}

void* SensorInterrupt::config(void *)
{
	if(ThreadCtl(_NTO_TCTL_IO, NULL) == -1)
	{
		perror("Failed to get I/O access permission");
		//return 1;
	}

	// Get a handle to the parallel port's Control Register
	intr_handle = mmap_device_io(1, 0x280 );
	if ( intr_handle == MAP_DEVICE_FAILED )
	{
		perror( "control map failed" );
		exit(EXIT_FAILURE);
	}
	out8(intr_handle, 0x02);

	interruptID = InterruptAttach(0x05, interruptReceived, NULL, 0, _NTO_INTR_FLAGS_PROCESS);
	if (interruptID == -1)
	{
		fprintf(stderr, "can't attach to IRQ %d\n", 0x05);
		perror(NULL);
		exit(EXIT_FAILURE);
	}
	out8(intr_handle, 0x02);
}


SensorInterrupt::~SensorInterrupt() {
	// TODO Auto-generated destructor stub
}
